# -*- coding: utf-8 -*-
"""
Created on 2024-06-13 16:34:58
---------
@summary:  appsflyer爬虫
---------
@author: Administrator
"""
import json
import logging
import os
from datetime import datetime

import feapder
import jmespath
import requests
from feapder.utils.log import log as logger
from encoders.DateTImeDecoder import DateTimeEncoder

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time


class Appsflyer(feapder.AirSpider):
    def __init__(self, data):
        super(Appsflyer, self).__init__()
        self.data = data
        self.thread_count = 1

    def start_requests(self):
        logger.info("开始爬虫")

        media_source = self.data['media_source']
        username = self.data['email']
        password = self.data['password']

        # 先登录
        # cookies = self._load_cookies(media_source, username, password)
        # 获取当前时间
        now = datetime.now()
        # 提取当前分钟数
        current_minute = now.minute
        cookies = self._login(media_source, username, password)

        day = self.data['day']
        now = self.data['now'].split(' ')[0]
        batch_id = self.data['batch_id']
        campaign = self.data['campaign']
        geo = self.data['geo']
        app_id = self.data["app_id"]

        data_url = "https://hq1.appsflyer.com/platform/dashboard?widget=platform-table:0"

        data_json = {
            "dates":{
                "start": day,
                "end": now
            },  
            "filters":{
                "app-id": [app_id],
            },
            "view-type": "unified",
            "localization": {
                "timezone" : "UTC",
                "currency" : "USD"
            },
            "groupings": [
                {
                    "dimension": "site-id",
                    "limit": 25
                }
            ],
            "summations": ["totals","others"],
            "metrics": [
                {
                    "metric-id": "clicks",
                    "filters": {},
                    "granularity": "",
                    "category": "core",
                    "period": "",
                    "platform-id": "filtersGranularityMetricIdClicksPeriod"
                },
                {
                    "metric-id": "installs",
                    "attribution-source": "appsflyer",
                    "filters": {},
                    "granularity": "",
                    "sort-by": {
                        "order": "desc",
                        "priority": 0
                    },
                    "category": "core",
                    "period": "",
                    "platform-id": "attributionSourceAppsflyerFiltersGranularityMetricIdInstallsPeriod"
                },
                {
                    "metric-id": "installs-ua",
                    "filters": {},
                    "attribution-source": "appsflyer",
                    "granularity": "",
                    "category": "core",
                    "period": "",
                    "platform-id": "attributionSourceAppsflyerFiltersGranularityMetricIdInstallsUaPeriod"
                },
                {
                    "metric-id": "installs-reattr",
                    "filters": {},
                    "attribution-source": "appsflyer",
                    "granularity": "",
                    "category": "core",
                    "period": "",
                    "platform-id": "attributionSourceAppsflyerFiltersGranularityMetricIdInstallsReattrPeriod"
                },
                {
                    "metric-id": "installs-retarget",
                    "filters": {},
                    "attribution-source": "appsflyer",
                    "granularity": "",
                    "category": "core",
                    "period": "",
                    "platform-id": "attributionSourceAppsflyerFiltersGranularityMetricIdInstallsRetargetPeriod"
                },
                {
                    "metric-id": "installs-cost",
                    "filters": {},
                    "granularity": "",
                    "category": "core",
                    "period": "",
                    "platform-id": "filtersGranularityMetricIdInstallsCostPeriod"
                },
                {
                    "metric-id": "ecpi",
                    "filters": {},
                    "attribution-source": "appsflyer",
                    "granularity": "",
                    "category": "calculated",
                    "period": "",
                    "platform-id": "attributionSourceAppsflyerFiltersGranularityMetricIdEcpiPeriod"
                },
                {
                    "metric-id": "revenue",
                    "filters": {},
                    "attribution-source": "appsflyer",
                    "aggregation-type": "cumulative",
                    "granularity": "days",
                    "category": "core",
                    "period": "activity",
                    "platform-id": "aggregationTypeCumulativeAttributionSourceAppsflyerFiltersGranularityDaysMetricIdRevenuePeriodActivity"
                },
                {
                    "metric-id": "revenue",
                    "filters": {},
                    "attribution-source": "appsflyer",
                    "aggregation-type": "cumulative",
                    "granularity": "days",
                    "category": "core",
                    "period": "ltv",
                    "platform-id": "aggregationTypeCumulativeAttributionSourceAppsflyerFiltersGranularityDaysMetricIdRevenuePeriodLtv"
                },
                {
                    "metric-id": "roas",
                    "filters": {},
                    "attribution-source": "appsflyer",
                    "aggregation-type": "cumulative",
                    "granularity": "days",
                    "category": "calculated",
                    "period": "1",
                    "platform-id": "aggregationTypeCumulativeAttributionSourceAppsflyerFiltersGranularityDaysMetricIdRoasPeriod1"
                },
                {
                    "metric-id": "roas",
                    "filters": {},
                    "attribution-source": "appsflyer",
                    "aggregation-type": "cumulative",
                    "granularity": "days",
                    "category": "calculated",
                    "period": "7",
                    "platform-id": "aggregationTypeCumulativeAttributionSourceAppsflyerFiltersGranularityDaysMetricIdRoasPeriod7"
                },
                {
                    "metric-id": "roas",
                    "filters": {},
                    "attribution-source": "appsflyer",
                    "aggregation-type": "cumulative",
                    "granularity": "days",
                    "category": "calculated",
                    "period": "ltv",
                    "platform-id": "aggregationTypeCumulativeAttributionSourceAppsflyerFiltersGranularityDaysMetricIdRoasPeriodLtv"
                },
                {
                    "metric-id": "retention-rate",
                    "filters": {},
                    "attribution-source": "appsflyer",
                    "aggregation-type": "on-period",
                    "granularity": "days",
                    "category": "calculated",
                    "period": "1",
                    "platform-id": "aggregationTypeOnPeriodAttributionSourceAppsflyerFiltersGranularityDaysMetricIdRetentionRatePeriod1"
                },
                {
                    "metric-id": "retention-rate",
                    "filters": {},
                    "attribution-source": "appsflyer",
                    "aggregation-type": "on-period",
                    "granularity": "days",
                    "category": "calculated",
                    "period": "3",
                    "platform-id": "aggregationTypeOnPeriodAttributionSourceAppsflyerFiltersGranularityDaysMetricIdRetentionRatePeriod3"
                }
            ],
            "format": "json",
            "granularity":"days"
        }

        yield feapder.Request(
            data_url,
            method="post",
            json=data_json,
            cookies=cookies,
            callback=self.parse_data,
            app_id=app_id,
            geo=geo,
            campaign=campaign,
            media_source=media_source,
            day=day,
            now=now,
            batch_id=batch_id,
            is_abandoned=True
        )

    def _login(self, pid, username, password):
        logger.info(f"使用 Selenium 无头浏览器登录 pid: {pid} 账号")
        chrome_options = Options()
        # chrome_options.add_argument('--headless')
        chrome_options.add_argument('--disable-gpu')
        chrome_options.add_argument('--no-sandbox')
        chrome_options.add_argument('--disable-dev-shm-usage')
        chrome_options.add_argument('--user-agent=Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36')
        chrome_options.add_argument('--disable-blink-features=AutomationControlled')
        driver = webdriver.Chrome(options=chrome_options)
        try:
            # 打开登录页面
            driver.get("https://hq1.appsflyer.com/auth/login")
            wait = WebDriverWait(driver, 5)  # 最长等待 20 秒
            # 等待用户名和密码输入框出现
            username_input = wait.until(EC.presence_of_element_located((By.NAME, "username")))
            password_input = wait.until(EC.presence_of_element_located((By.NAME, "password")))
            username_input.clear()
            username_input.send_keys(username)
            password_input.clear()
            password_input.send_keys(password)
            # 等待并点击登录按钮
            login_button = wait.until(
                EC.element_to_be_clickable((By.XPATH, "//button[@type='submit']"))
            )
            login_button.click()
            wait.until(lambda d: "dashboard" in d.current_url.lower() or "hq1.appsflyer.com" in d.current_url)
            time.sleep(5)
            cookies_list = driver.get_cookies()
            cookies_map = {c['name']: c['value'] for c in cookies_list}
            required_cookies = ["af_jwt", "auth_tkt", "aws-waf-token"]
            if all(k in cookies_map for k in required_cookies):
                return cookies_map
            else:
                logger.warning(f"未获取到全部关键 Cookie, 当前有: {list(cookies_map.keys())}")
                return False
        finally:
            driver.quit()

    def parse_data(self, request, response):
        logger.info("开始解析")
        app_id = request.app_id
        geo = request.geo
        media_source = request.media_source
        campaign = request.campaign
        day = request.day
        now = request.now
        batch_id = request.batch_id
        res_data_list = []

        try:
            data = response.json
            site_id_datas = data['data']
            for sid in site_id_datas:
                site_id = sid['site-id']
                installs = sid.get('attributionSourceAppsflyerFiltersGranularityMetricIdInstallsPeriod', 0)
                clicks = sid.get('filtersGranularityMetricIdClicksPeriod', 0)
                logger.info(f"siteid: {site_id}, installs: {installs}, clicks: {clicks}")

                res_data = {'appId': app_id, 'geo': geo, 'mediaSource': media_source, 'campaign': campaign,
                            'clicks': clicks, 'impressions': 0, 'installs': installs, 'siteId': site_id}   
                res_data_list.append(res_data)
        except Exception as e:
            logger.error(e)
        finally:
            res_data_day = {
                "day": day,
                "now": now,
                "batchId": batch_id,
                "afDailyReports": res_data_list
            }
            self.report_data(res_data_day)

    def report_data(self, json_data):
        report_url = "http://13.215.154.56:8001/v1/aspen/appsflyer/data"
        # report_url = "http://localhost:8001/v1/aspen/appsflyer/data"
        logger.info(f"上报数据: {json_data}")
        headers = {"Content-Type": "application/json"}
        json_data_dump = json.dumps(json_data, cls=DateTimeEncoder)
        resp = requests.post(
            url=report_url, headers=headers, data=json_data_dump
        )
        if resp.status_code != 200:
            logger.error(f"上报数据失败:\n {json_data}")


